/*-----------------------------------------------------------------------------
 * @file   hal_uart.h
 * @brief  interface for uart/usart module operations
 * @author WLH<wanglehui8357@163.com> Copyright (C) 2021~2099.
-----------------------------------------------------------------------------*/
#ifndef HAL_UART_H
#define HAL_UART_H

#include "globaldef.h"

BEGIN_DECLS

/*-----------------------------------------------------------------------------
 * SerialPort ID Macros
-----------------------------------------------------------------------------*/
#define HAL_COM0     0u
#define HAL_COM1     1u
#define HAL_COM2     2u
#define HAL_COM3     3u
#define HAL_COM_NULL 0xFFu /* Invalid COM Port     */

/*-----------------------------------------------------------------------------
 * Baudrate Macros
-----------------------------------------------------------------------------*/
#define HAL_BAUDRATE_9600   0u
#define HAL_BAUDRATE_19200  1u
#define HAL_BAUDRATE_38400  2u
#define HAL_BAUDRATE_57600  3u
#define HAL_BAUDRATE_115200 4u
#define HAL_BAUDRATE_230400 5u
#define HAL_BAUDRATE_460800 6u
#define HAL_BAUDRATE_921600 7u

/* Specail value for SBUS [100KHz]*/
#define HAL_BAUDRATE_100000 10u

#define IS_BAUD_RATE(a) ((a) == HAL_BAUDRATE_100000 || \
                         (a) <= HAL_BAUDRATE_921600)

/**
 * @brief  Map HAL_BAUDRATE_XXX to real value
 * @return return 9600U if a == HAL_BAUDRATE_9600
 */
static inline U32 hal_baud_rate_val(const U8 a)
{
    if (HAL_BAUDRATE_9600 == a)
    {
        return 9600u;
    }
    if (HAL_BAUDRATE_19200 == a)
    {
        return 19200u;
    }
    if (HAL_BAUDRATE_38400 == a)
    {
        return 38400u;
    }
    if (HAL_BAUDRATE_57600 == a)
    {
        return 57600u;
    }
    if (HAL_BAUDRATE_115200 == a)
    {
        return 115200u;
    }
    if (HAL_BAUDRATE_230400 == a)
    {
        return 230400u;
    }
    if (HAL_BAUDRATE_460800 == a)
    {
        return 460800u;
    }
    if (HAL_BAUDRATE_921600 == a)
    {
        return 921600u;
    }

    /* special value for SBUS (100Khz) */
    if (HAL_BAUDRATE_100000 == a)
    {
        return 100000u;
    }

    return 9600u;
}

/*-----------------------------------------------------------------------------
 * Parity Macros
-----------------------------------------------------------------------------*/
#define HAL_UART_PARITY_NONE 0x00u
#define HAL_UART_PARITY_ODD  0x01u
#define HAL_UART_PARITY_EVEN 0x02u

#define IS_HAL_UART_PARITY(a) (((a) == HAL_UART_PARITY_NONE) || \
                               ((a) == HAL_UART_PARITY_ODD) ||  \
                               ((a) == HAL_UART_PARITY_EVEN))

/*-----------------------------------------------------------------------------
 * StopBit Macros
-----------------------------------------------------------------------------*/
#define HAL_UART_STOPBIT_1   0x00u
#define HAL_UART_STOPBIT_1_5 0x01u
#define HAL_UART_STOPBIT_2   0x02u

#define IS_HAL_UART_STOPBIT(a) (((a) == HAL_UART_STOPBIT_1) ||   \
                                ((a) == HAL_UART_STOPBIT_1_5) || \
                                ((a) == HAL_UART_STOPBIT_2))

/*-----------------------------------------------------------------------------
 * DataBit Macros
-----------------------------------------------------------------------------*/
#define HAL_UART_DATABIT_5 0x05u
#define HAL_UART_DATABIT_6 0x06u
#define HAL_UART_DATABIT_7 0x07u
#define HAL_UART_DATABIT_8 0x08u
#define HAL_UART_DATABIT_9 0x09u

#define IS_HAL_UART_DATABIT(a) (((a) >= HAL_UART_DATABIT_5) && \
                                ((a) <= HAL_UART_DATABIT_9))

/*-----------------------------------------------------------------------------
 * Callback functions type when data arrived, invoked in ISR
-----------------------------------------------------------------------------*/
typedef void (*UART_RX_READY_CB)(const U8 port_num);

/*-----------------------------------------------------------------------------
 * uart configure struct
-----------------------------------------------------------------------------*/
typedef struct
{
    U8 baudrate; /* Use HAL_BAUDRATE_xxxx   */
    U8 databit;  /* Use HAL_UART_DATABIT_xx */
    U8 stopbit;  /* Use HAL_UART_STOPBIT_xx */
    U8 parity;   /* Use HAL_UART_PARITY_xx  */
} uart_cfg_t;

/*-----------------------------------------------------------------------------
 * public functions declaration
-----------------------------------------------------------------------------*/
/**
 * @brief      global init for all UART controller
 */
void hal_uart_global_init(void);

/**
 * @brief      init UART controller
 *
 * @param[in]  port_num  The port number
 * @param[in]  cfg       The configuration
 */
bool hal_uart_init(const U8 port_num, const uart_cfg_t* cfg);

/**
 * @brief      init UART HUB interface
 *
 * @param[in]  port_num  The port number
 * @param[in]  cfg       The configuration
 */
bool hal_uart_init_as_hub(const U8 port_num);

/**
 * @brief      Configure baudrate after initial
 *
 * @param[in]  port_num  The port number
 * @param[in]  baudrate  The baudrate by HAL_BAUDRATE_XX
 */
bool hal_uart_set_baudrate(const U8 port_num, const U8 baudrate);

/**
 * @brief      register call back function to indicate data is ready
 *
 * @param[in]  port_num  The port number
 * @param[in]  cb_fun    The call back function
 */
void hal_uart_reg_rx_ready(const U8 port_num, UART_RX_READY_CB cb_fun);

/**
 * @brief      read data from UART/USART device to buffer
 * @param[in]  port_num  The port number
 * @param      buf       The buffer data pointer
 * @param[in]  bufSize   The buffer size
 * @return     size of read data
 */
U32 hal_uart_read(const U8 port_num, U8* buf, U32 buf_size);

/**
 * @brief      write data to UART/USART device
 * @param[in]  port_num  The port number
 * @param      data      The data pointer
 * @param[in]  data_size The length of data in byte
 * @return     size of write data
 */
U32 hal_uart_write(const U8 port_num, const U8* data, U32 data_size);

END_DECLS

#endif //~HAL_UART_H
